package com.yimils.core.sys.beanUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yimils.core.sys.entity.ResourceEntity;
import com.yimils.core.sys.entity.RoleResourceEntity;
import com.yimils.core.sys.entity.UserRoleEntity;
import com.yimils.core.sys.service.ResourceService;
import com.yimils.core.sys.service.RoleResourceService;
import com.yimils.core.sys.service.UserRoleService;
import com.yimils.core.sys.vo.UserMenuVo;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class UserResourceUtil {

    @Resource(name = "resourceService")
    private ResourceService resourceService;

    @Resource(name = "userRoleService")
    private UserRoleService userRoleService;

    @Resource(name = "roleResourceService")
    private RoleResourceService roleResourceService;

    /**
     * 获取系统资源树结构
     *
     * @param userId   用户所属资源，获取全部传NULL
     * @param hasPerms 是否获取权限级资源，左侧菜单渲染不需要权限级资源
     * @return
     */
    public List<UserMenuVo.Menu> getMenuTree(Long userId, boolean hasPerms) {
        if (userId == null) {
            return getMenuTreeAll(hasPerms);
        } else {
            return getMenuTreeByUserId(userId, hasPerms);
        }
    }

    private List<UserMenuVo.Menu> getMenuTreeAll(boolean hasPerms) {
        List<ResourceEntity> dirs = resourceService.getDirAll();
        List<UserMenuVo.Menu> tree = new ArrayList<>();
        for (ResourceEntity dir : dirs) {//构建目录
            UserMenuVo.Menu dirVo = makeTreeNode(dir);
            tree.add(dirVo);
            List<ResourceEntity> menus = resourceService.getMenuAll(dir.getId());
            dirVo.setChildren(new ArrayList<>());
            for (ResourceEntity menu : menus) {//构建菜单
                UserMenuVo.Menu menuVo = makeTreeNode(menu);
                dirVo.getChildren().add(menuVo);
                if (hasPerms) {
                    List<ResourceEntity> perms = resourceService.getPermAll(menu.getId());
                    menuVo.setChildren(new ArrayList<>());
                    for (ResourceEntity perm : perms) {
                        UserMenuVo.Menu permVo = makeTreeNode(perm);
                        menuVo.getChildren().add(permVo);
                    }
                }
            }
        }
        return tree;
    }

    private List<UserMenuVo.Menu> getMenuTreeByUserId(Long userId, boolean hasPerms) {
        QueryWrapper<UserRoleEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(UserRoleEntity::getUserId, userId);
        List<UserRoleEntity> userRoles = userRoleService.list(qw);
        QueryWrapper<RoleResourceEntity> qwR = null;
        List<RoleResourceEntity> roleResources = new ArrayList<>();
        for (UserRoleEntity userRole : userRoles) {
            qwR = new QueryWrapper<>();
            qwR.lambda().eq(RoleResourceEntity::getRoleId, userRole.getRoleId()).eq(RoleResourceEntity::getActive, 1);
            List<RoleResourceEntity> tmp = roleResourceService.list(qwR);
            roleResources.addAll(tmp);
        }
        List<Long> tmpList = new ArrayList<>();
        roleResources = roleResources.stream().filter(// 过滤去重
                v -> {
                    boolean flag = !tmpList.contains(v.getResourceId());
                    tmpList.add(v.getResourceId());
                    return flag;
                }
        ).sorted(Comparator.comparing(RoleResourceEntity::getResourceId)).collect(Collectors.toList());
        List<UserMenuVo.Menu> templateTree = getMenuTreeAll(hasPerms);
        List<UserMenuVo.Menu> dirTree = new ArrayList<>();
        List<UserMenuVo.Menu> menuTree = new ArrayList<>();
        for (UserMenuVo.Menu dir : templateTree) {
            if (dir.getType().equals(ResourceService.TYPE_DIR)) {
                for (RoleResourceEntity roleResource : roleResources) {
                    if (roleResource.getResourceId().equals(dir.getId())) {
                        dirTree.add(dir);
                    }
                }
            }
            for (UserMenuVo.Menu menu : dir.getChildren()) {
                if (menu.getType().equals(ResourceService.TYPE_SUB)) {
                    for (RoleResourceEntity roleResource : roleResources) {
                        if (roleResource.getResourceId().equals(menu.getId())) {
                            menuTree.add(menu);
                        }
                    }
                }
            }
        }
        for (UserMenuVo.Menu dir : dirTree) {
            dir.getChildren().clear();
            for (UserMenuVo.Menu menu : menuTree) {
                if (menu.getParentId().equals(dir.getId())) {
                    dir.getChildren().add(menu);
                }
            }
        }
        return dirTree;
    }


    private UserMenuVo.Menu makeTreeNode(ResourceEntity res) {
        UserMenuVo.Menu node = new UserMenuVo.Menu();
        node.setId(res.getId());
        node.setParentId(res.getParentId());
        node.setName(res.getName());
        node.setType(res.getType());
        node.setTitle(res.getTitle());
        node.setIcon(res.getIcon());
        node.setOpt(res.getOpt());
        node.setPath(res.getUrl());
        node.setSys(res.getSys());
        node.setSort(res.getSort());
        return node;
    }

    public List<Long> entitiesToArray(List<ResourceEntity> resources) {
        List<Long> array = new ArrayList<>();
        for (ResourceEntity resource : resources) {
            array.add(resource.getId());
        }
        return array;
    }
}
